package SGNet2

import (
	"net"
	"sync"

	"git.oschina.net/yangdao/extlib"
	. "git.oschina.net/yangdao/extlib/data_type"
	. "git.oschina.net/yangdao/extlib/libInterface"
)

var mlog ILog

const (
	SGNetMsg_SessionLost = 0
	SGNetMsg_SessionNew  = 1
)

func SetLog(serverlog ILog) {
	mlog = serverlog
}
func Log(strTag string, values ...interface{}) {
	if mlog != nil {
		mlog.Log(strTag, values...)
	}
}

type NetServer struct {
	Protocol       IProtocl
	addSessionLock sync.Mutex
	Sessions       map[int64]*Session
	ServerConfig   IAssociative
	SGNetMessage   func(sess *Session, MsgType int)
}

func NewNetServer(config IAssociative, log ILog, protocol IProtocl) *NetServer {
	RetNetServer := &NetServer{
		Sessions:     make(map[int64]*Session),
		ServerConfig: config,
		Protocol:     protocol,
	}
	SetLog(log)
	return RetNetServer
}

func (this *NetServer) Run() {
	if !this.ServerConfig.ContainsKey("port") {
		panic("配置字典中没有端口port参数")
	}
	port := this.ServerConfig.Get("port").(string)
	tcpAddr, err := net.ResolveTCPAddr("tcp4", ":"+port)
	if err != nil {
		Log("Error,Server", err)
		return
	}
	listener, err := net.ListenTCP("tcp", tcpAddr)
	if err != nil {
		Log("Error,Server", err)
		return
	}
	Log("Server.Info,Server", "NetServer Start Port:"+port)

	for {
		conn, err := listener.Accept()
		if err != nil {
			Log("Error,Server", err)
			continue
		}
		sess := this.NewSession(conn, this)
		this.AddSession(sess)
		Log("Server.DetailInfo,Server", "开始了一个新的Session(", sess.ID, sess.Conn.RemoteAddr().String(), ")当前Session数[", len(this.Sessions), "]")

		go sess.loop()
	}
}

func (this *NetServer) AddPacketEvent(fn interface{}) {
	this.Protocol.AddPacketEvent(fn)
}

func (this *NetServer) NewSession(conn net.Conn, server *NetServer) *Session {
	newSession := &Session{
		ID:     extlib.Int64UUID(),
		Conn:   conn,
		Server: server,
	}

	newSession.in = make(chan interface{}, 64)
	newSession.out = make(chan interface{}, 64)
	return newSession
}

func (this *NetServer) AddSession(sess *Session) {
	this.addSessionLock.Lock()
	this.Sessions[sess.ID] = sess
	if this.SGNetMessage != nil {
		this.SGNetMessage(sess, SGNetMsg_SessionNew)
	}
	this.addSessionLock.Unlock()
}

//RemoveSession 移除一个会话
func (server *NetServer) RemoveSession(sess *Session) {

	delete(server.Sessions, sess.ID)
	Log("Server.DetailInfo,Server", "一个Session已被移除", sess.ID, "当前Session数[", len(server.Sessions), "]")
	if server.SGNetMessage != nil {
		server.SGNetMessage(sess, SGNetMsg_SessionLost)
	}

}
